package activityservice

import (
	"encoding/json"
	"fmt"
	"games.com/server/internal/pkg/config"
	pkghttp "games.com/server/internal/pkg/http"
	"net/http"
)

type activityService struct {
	dao    *activityDAO
	config *config.Config
}

func NewActivityService(config *config.Config) (*activityService, error) {
	as := &activityService{config: config}

	dao, err := NewActivityDAO(config)
	if err != nil {
		return nil, fmt.Errorf("failed to new Activitydao, err:%w", err)
	}
	as.dao = dao

	http.HandleFunc("/AddActivity", as.addActivityHandler)
	http.HandleFunc("/DeleteActivity", as.deleteActivityHandler)
	http.HandleFunc("/UpdateActivity", as.updateActivityHandler)
	http.HandleFunc("/QueryActivityCnt", as.queryActivityCntHandler)
	http.HandleFunc("/QueryActivity", as.queryActivityHandler)

	return as, nil
}

func (as *activityService) addActivityHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	var req Activity
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusBadRequest)
		return
	}

	ctx := r.Context()
	err = as.dao.InsertActivity(ctx, &req)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to insert activity, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}
	resJson, err := json.Marshal(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resJson)
}

type DeleteActivityReq struct {
	ID int32 `json:"id"`
}

func (as *activityService) deleteActivityHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	var req DeleteActivityReq
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusBadRequest)
		return
	}

	ctx := r.Context()
	err = as.dao.DeleteActivity(ctx, req.ID)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to delete activity, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
}

func (as *activityService) updateActivityHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	var req Activity
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusBadRequest)
		return
	}

	ctx := r.Context()

	record, err := as.dao.QueryActivityByID(ctx, req.ID)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to query activity by id, err:%w", err).Error(), http.StatusBadRequest)
		return
	}

	record.Gm = req.Gm
	record.ActivityName = req.ActivityName
	record.ActivityID = req.ActivityID
	record.StartTime = req.StartTime
	record.EndTime = req.EndTime

	err = as.dao.UpdateActivity(ctx, record)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to insert activity, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}
	resJson, err := json.Marshal(record)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resJson)
}

type QueryActivityCntRes struct {
	Cnt int32 `json:"cnt"`
}

func (as *activityService) queryActivityCntHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	ctx := r.Context()
	cnt, err := as.dao.QueryActivityCnt(ctx)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("query activity cnt failed, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}
	res := &QueryActivityCntRes{Cnt: cnt}
	resJson, err := json.Marshal(res)
	if err != nil {
		pkghttp.HttpError(w, "query activity cnt failed", http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resJson)
}

type QueryActivityReq struct {
	PageCapacity int32 `json:"page_capacity"`
	Page         int32 `json:"page"`
}
type QueryActivityRes struct {
	Activities []*Activity `json:"activities"`
}

func (as *activityService) queryActivityHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	var req QueryActivityReq
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to decode json, err:%w", err).Error(), http.StatusBadRequest)
		return
	}

	ctx := r.Context()
	start := (req.Page - 1) * req.PageCapacity
	offset := req.PageCapacity
	activities, err := as.dao.QueryActivity(ctx, start, offset)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to query activity, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}
	res := QueryActivityRes{Activities: activities}
	resJson, err := json.Marshal(&res)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resJson)
}
